package com.vdong.trade.trading.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.vdong.trade.order.facade.OrderFacade;
import com.vdong.trade.order.facade.enums.EventEnum;
import com.vdong.trade.trading.common.constants.WechatPayConstants;
import com.vdong.trade.trading.common.context.PaymentContext;
import com.vdong.trade.trading.common.context.WechatPaymentContext;
import com.vdong.trade.trading.common.contract.AbstractResponse;
import com.vdong.trade.trading.common.enums.PayReturnCodeEnum;
import com.vdong.trade.trading.common.exception.ServiceException;
import com.vdong.trade.trading.common.exception.ValidateException;
import com.vdong.trade.trading.common.utils.WechatPayUtil;
import com.vdong.trade.trading.common.utils.HttpClientUtil;
import com.vdong.trade.trading.entity.dto.param.*;
import com.vdong.trade.trading.entity.dto.result.PaymentNotifyResponseDTO;
import com.vdong.trade.trading.entity.dto.result.PaymentResponseDTO;
import com.vdong.trade.trading.entity.mo.PayConfigMO;
import com.vdong.trade.trading.entity.mo.WechatPayDataExampleMo;
import com.vdong.trade.trading.entity.mo.WechatPayDataMo;
import com.vdong.trade.trading.entity.mo.WechatPayDataWithBLOBsMo;
import com.vdong.trade.trading.facade.enums.PayChannelEnum;
import com.vdong.trade.trading.facade.enums.PayConfigEnum;
import com.vdong.trade.trading.facade.enums.WechatPayEnums;
import com.vdong.trade.trading.respository.WechatPayDataMapper;
import com.vdong.trade.trading.service.BasePayment;
import com.vdong.trade.trading.service.PayConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.lamb.framework.common.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;

/**
 * @author <a href="mailto:clf@vdongzc.com">clf</a>
 * @Description: 微信支付
 * @Date Create on 2018-12-13 15:10:22
 * @since version1.0
 */
@Service
@Slf4j
public class WechatPayment extends BasePayment {

    @Autowired
    private WechatPayDataMapper wechatPayDataMapper;

    @Autowired
    private TradeDynamicPropertyService tradeDynamicPropertyService;

    @Autowired
    private PayConfigService payConfigService;

    @Reference
    private OrderFacade orderFacade;

    private static ThreadLocal<PayConfigMO> threadLocal = new ThreadLocal<>();

    private void initPayConfigMO() {
        // 获取商户支付信息
        PayConfigParamDTO dto = new PayConfigParamDTO();
        dto.setType(PayConfigEnum.OFFICIAL_ACCOUNT.getCode());
        List<PayConfigMO> moList = payConfigService.selectPayConfigList(dto);
        if (CollectionUtils.isEmpty(moList)) {
            throw new ServiceException("获取商户支付信息失败!");
        }
        threadLocal.set(moList.get(0));
    }

    @Override
    public void validator(PaymentRequestDTO request) {
        if (request == null) {
            throw new ValidateException("请求参数为空!");
        }
        if (StringUtil.hasBlank(request.getOrderType())) {
            throw new ValidateException("订单业务类型 ==> orderType不能为空!");
        }
        if (StringUtil.hasBlank(request.getTotalFee())) {
            throw new ValidateException("实际支付金额 => totalFee不能为空!");
        }
        if (StringUtil.hasBlank(request.getSpbillCreateIp())) {
            throw new ValidateException("终端IP ==> spbillCreateIp不能为空!");
        }
        if (StringUtil.hasBlank(request.getPayChannel())) {
            throw new ValidateException("支付渠道 ==> payChannel不能为空!");
        }
        if (StringUtil.hasBlank(request.getOrderNo())) {
            throw new ValidateException("交易系统传递的订单号 ==> orderNo不能为空!");
        }


        // 个人转商户
        if (WechatPayEnums.OrderTypeEnum.USER_PAY.getType().equals(request.getOrderType())) {
            if (StringUtil.hasBlank(request.getTradeType())) {
                throw new ValidateException("支付方式 ==> tradeType不能为空!");
            }

            if (StringUtil.hasBlank(request.getBody())) {
                throw new ValidateException("商品描述 ==> body不能为空!");
            }

            if (WechatPayEnums.TradeTypeEnum.JSAPI1.getCode().equals(request.getTradeType()) ||
                    WechatPayEnums.TradeTypeEnum.JSAPI2.getCode().equals(request.getTradeType())) {
                if (StringUtil.hasBlank(request.getOpenid())) {
                    throw new ValidateException("用户标识 ==> openid不能为空!");
                }
            } else if (WechatPayEnums.TradeTypeEnum.NATIVE.getCode().equals(request.getTradeType())) {
                if (StringUtil.hasBlank(request.getOpenid())) {
                    throw new ValidateException("商品id ==> productId不能为空!");
                }
            }
        } else if (WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(request.getOrderType())) {
            // 商户转个人
            if (StringUtil.hasBlank(request.getDesc())) {
                throw new ValidateException("企业付款备注 ==> desc不能为空!");
            }
            if (StringUtil.hasBlank(request.getOpenid())) {
                throw new ValidateException("用户标识 ==> openid不能为空!");
            }
        }


    }

    /**
     * orderFee:订单金额
     * payChannel:支付方式
     * spbillCreateIp:ip
     * subject:商品名称
     * totalFee:总金额
     * tradeNo:订单号
     * userId:用户id
     *
     * @param request
     */
    @Override
    public PaymentContext createContext(PaymentRequestDTO request) {
        this.initPayConfigMO();

        WechatPaymentContext wechatPaymentContext = new WechatPaymentContext();

        // ip
        wechatPaymentContext.setSpbillCreateIp(request.getSpbillCreateIp());
        // body
        wechatPaymentContext.setBody(request.getBody());
        // nonceStr 随机字符串
        wechatPaymentContext.setNonceStr(WechatPayUtil.generateNonceStr());

        // 个人转商户
        if (WechatPayEnums.OrderTypeEnum.USER_PAY.getType().equals(request.getOrderType())) {
            if (WechatPayEnums.TradeTypeEnum.JSAPI1.getCode().equals(request.getTradeType())) {
                // 小程序支付
                wechatPaymentContext.setTradeType(WechatPayEnums.TradeTypeEnum.JSAPI1.getType());
                wechatPaymentContext.setOpenid(request.getOpenid());
            } else if (WechatPayEnums.TradeTypeEnum.JSAPI2.getCode().equals(request.getTradeType())) {
                // 公众号支付
                wechatPaymentContext.setTradeType(WechatPayEnums.TradeTypeEnum.JSAPI2.getType());
                wechatPaymentContext.setOpenid(request.getOpenid());
            } else if (WechatPayEnums.TradeTypeEnum.NATIVE.getCode().equals(request.getTradeType())) {
                // 扫码支付(product_id必传)
                wechatPaymentContext.setTradeType(WechatPayEnums.TradeTypeEnum.NATIVE.getType());
                wechatPaymentContext.setProductId(request.getProductId());
            } else if (WechatPayEnums.TradeTypeEnum.APP.getCode().equals(request.getTradeType())) {
                // app支付
                wechatPaymentContext.setTradeType(WechatPayEnums.TradeTypeEnum.APP.getType());
            }
            //订单号
            wechatPaymentContext.setOutTradeNo(WechatPayUtil.getUUID());
            // totalFee
            wechatPaymentContext.setTotalFee(request.getTotalFee().toString());
            wechatPaymentContext.setAppid(threadLocal.get().getAppId());
            wechatPaymentContext.setMchId(threadLocal.get().getMchId());
            wechatPaymentContext.setNotifyUrl(tradeDynamicPropertyService.getWechatNotifyurl());
            if (!StringUtil.hasBlank(request.getKpayOrderNo())) {
                wechatPaymentContext.setAttach(request.getKpayOrderNo());
            }
        } else if (WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(request.getOrderType())) {
            // 商户转个人
            wechatPaymentContext.setMchAppid(threadLocal.get().getAppId());
            wechatPaymentContext.setMchid(threadLocal.get().getMchId());
            // 订单号
            wechatPaymentContext.setPartnerTradeNo(WechatPayUtil.getUUID());
            wechatPaymentContext.setOpenid(request.getOpenid());
            wechatPaymentContext.setAmount(request.getTotalFee().toString());
            wechatPaymentContext.setDesc(request.getDesc());
            wechatPaymentContext.setCheckName(WechatPayConstants.NO_CHECK);
        }
        return wechatPaymentContext;
    }

    /**
     * @param request orderFee:订单金额
     *                payChannel:支付方式
     *                spbillCreateIp:ip
     *                subject:商品名称
     *                totalFee:总金额
     *                tradeNo:订单号
     *                userId:用户id
     * @param context outTradeNo:商户订单号
     */
    @Override
    public void prepare(PaymentRequestDTO request, PaymentContext context) {
        WechatPaymentContext paymentContext = (WechatPaymentContext) context;
        SerializeConfig config = new SerializeConfig();
        config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
        String str = JSON.toJSONString(context, config);
        Map<String, String> paraMap = JSON.parseObject(str, HashMap.class);

        //是否走沙盒测试
        if (false) {
            Map<String, String> data = new HashMap<>();
            data.put("mch_id", paymentContext.getMchId());
            data.put("nonce_str", WechatPayUtil.generateNonceStr());
            String xml = "";
            try {
                xml = WechatPayUtil.generateSignedXml(data, threadLocal.get().getPayKey());

                String xmlStr = HttpClientUtil.httpPost(WechatPayConstants.shaheurl, xml);
                System.out.println("沙盒微信调用返回结果:" + JSON.toJSONString(xmlStr));

                Map<String, String> resultMap = WechatPayUtil.xmlToMap(xmlStr);

                if ("SUCCESS".equals(resultMap.get("return_code"))) {
                    //表示订单处理成功
                    //request.setPayKey(resultMap.get("sandbox_signkey"));
                } else {
                    throw new RuntimeException("沙盒测试接口调用异常");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("沙盒测试接口调用异常");
            }
        }

        String xml = null;
        try {
            xml = WechatPayUtil.generateSignedXml(paraMap, threadLocal.get().getPayKey());
        } catch (Exception e) {
            log.error("微信支付请求入参加密异常:", e);
            throw new ServiceException("支付参数加密异常!");
        }
        paymentContext.setXml(xml);
        //TODO 保存订单记录, 由于微信是属于预提交请求，需要对当前交易做幂等性，还需要控制二维码的时效


        WechatPayDataWithBLOBsMo mo = new WechatPayDataWithBLOBsMo();
        //订单业务类型
        mo.setOrderType(request.getOrderType().shortValue());
        //状态
        mo.setStatus(WechatPayEnums.PayStatusEnum.PAY_INIT.getStatus());

        //订单号
        if (WechatPayEnums.OrderTypeEnum.USER_PAY.getType().equals(request.getOrderType())) {
            // 个人转商户
            mo.setOutTradeNo(paymentContext.getOutTradeNo());
            //微信支付类型
            mo.setTradeType(request.getTradeType().shortValue());
        } else if (WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(request.getOrderType())) {
            // 商户转个人
            mo.setOutTradeNo(paymentContext.getPartnerTradeNo());
        }
        //请求时间
        mo.setRequestTime(new Date());
        //请求参数报文
        mo.setRequest(JSON.toJSONString(paraMap));
        //totalFee
        mo.setTotalFee(request.getTotalFee());
        mo.setNonceStr(paymentContext.getNonceStr());
        mo.setOrderNo(request.getOrderNo());
        wechatPayDataMapper.insertSelective(mo);
    }


    @Override
    public AbstractResponse generalProcess(PaymentRequestDTO request, PaymentContext context) throws Exception {
        WechatPaymentContext wechatPaymentContext = (WechatPaymentContext) context;

        //商户转个人
        String postUrl;
        String xmlStr = null;
        if (this.getIsUserOrMerchantFlag(request.getOrderType())) {
            postUrl = tradeDynamicPropertyService.getWechatTransfersOrder();
            InputStream sbs = new ByteArrayInputStream(threadLocal.get().getPayCert());
            xmlStr = HttpClientUtil.httpPost(postUrl, wechatPaymentContext.getXml(), threadLocal.get().getMchId(), sbs, true);
        } else {
            postUrl = tradeDynamicPropertyService.getWechatUnifiedOrder();
            xmlStr = HttpClientUtil.httpPost(postUrl, wechatPaymentContext.getXml());
        }

        log.info("wechatPayment. generalProcess response：" + xmlStr);
        //验证签名
        Map<String, String> resultMap = WechatPayUtil.xmlToMap(xmlStr);

        log.info("同步返回参数:[{}]", JSON.toJSONString(resultMap));

        wechatPaymentContext.setResultMap(resultMap);

        PaymentResponseDTO response = new PaymentResponseDTO();

        if (WechatPayConstants.FAIL.equals(resultMap.get(WechatPayConstants.RETURN_CODE))) {
            response.setCode(PayReturnCodeEnum.PAYMENT_PROCESSOR_FAILED.getCode());
            response.setMsg(PayReturnCodeEnum.PAYMENT_PROCESSOR_FAILED.getMsg(
                    resultMap.get(WechatPayConstants.RETURN_MSG)));
            return response;
        }

        if (WechatPayConstants.FAIL.equals(resultMap.get(WechatPayConstants.RESULT_CODE))) {
            String errCode = resultMap.get(WechatPayConstants.ERR_CODE);
            // 商户转个人时: errCode== SYSTEMERROR 此时订单状态不明确
            if (WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(request.getOrderType())) {
                if (WechatPayConstants.SYSTEMERROR.equals(errCode)) {
                    response.setCode(PayReturnCodeEnum.THIRD_SYSTEM_ERROR.getCode());
                    response.setMsg(PayReturnCodeEnum.THIRD_SYSTEM_ERROR.getMsg());
                    return response;
                }
            }

            String errMsg = errCode + ":" + resultMap.get(WechatPayConstants.ERR_CODE_DES);
            response.setCode(PayReturnCodeEnum.PAYMENT_PROCESSOR_FAILED.getCode());
            response.setMsg(PayReturnCodeEnum.PAYMENT_PROCESSOR_FAILED.getMsg(errMsg));
            return response;
        }

        // 商户转个人成功的业务处理
        if (WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(request.getOrderType())) {
            String paymentNo = resultMap.get(WechatPayConstants.PAYMENT_NO);
            response.setPaymentNo(paymentNo);
            response.setCode(PayReturnCodeEnum.SUCCESS.getCode());
            return response;
        }

        // 个人转商户成功的业务处理
        // 表示订单处理成功
        String tradeType = resultMap.get(WechatPayConstants.TRADE_TYPE);
        if (WechatPayEnums.TradeTypeEnum.JSAPI1.getType().equals(tradeType)) {
            //小程序/公众号
            response.setAppId(resultMap.get(WechatPayConstants.APPID));
            response.setTimeStamp(String.valueOf((System.currentTimeMillis() / 1000)));
            response.setNonceStr(resultMap.get(WechatPayConstants.NONCE_STR));
            response.setPackageValue(WechatPayConstants.PREPAY_ID_STR + resultMap.get(WechatPayConstants.PREPAY_ID));
            response.setSignType(WechatPayConstants.SignType.MD5.name());
            Map<String, String> map = beanToMap(response);
            log.info("调用微笑支付接口成功:生成支付paySign的参数:[{}]", JSON.toJSONString(map));
            response.setPaySign(WechatPayUtil.generateSignature(map, threadLocal.get().getPayKey()));
        } else if (WechatPayEnums.TradeTypeEnum.NATIVE.getType().equals(tradeType)) {
            //扫码
            response.setCodeUrl(resultMap.get(WechatPayConstants.CODE_URL));
        } else {
            //app
        }
        response.setCode(PayReturnCodeEnum.SUCCESS.getCode());

        try {

        } finally {

            threadLocal.remove();
        }

        return response;
    }

    /**
     * 获取业务交易类型
     *
     * @param orderType
     * @return true:商户转个人 false:个人转商户/个人退款
     */
    private Boolean getIsUserOrMerchantFlag(Integer orderType) {
        return WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(orderType);
    }

    @Override
    public void afterProcess(PaymentRequestDTO request, AbstractResponse response, PaymentContext context) {
        WechatPaymentContext paymentContext = (WechatPaymentContext) context;
        PaymentResponseDTO paymentResponseDTO = (PaymentResponseDTO) response;

        WechatPayDataExampleMo wechatDataExampleMo = new WechatPayDataExampleMo();
        wechatDataExampleMo.createCriteria().andNonceStrEqualTo(paymentContext.getNonceStr())
                .andStatusEqualTo(WechatPayEnums.PayStatusEnum.PAY_INIT.getStatus());
        List<WechatPayDataMo> list = wechatPayDataMapper.selectByExample(wechatDataExampleMo);
        if (CollectionUtils.isEmpty(list)) {
            log.error("微信支付订单同步回调获取订单信息失败 ==> nonceStr:[{}]", paymentContext.getNonceStr());
            return;
        }

        WechatPayDataExampleMo updateWechatDataExampleMo = new WechatPayDataExampleMo();
        updateWechatDataExampleMo.createCriteria().andIdEqualTo(list.get(0).getId())
                .andStatusEqualTo(WechatPayEnums.PayStatusEnum.PAY_INIT.getStatus());


        WechatPayDataWithBLOBsMo updateWechatDataMo = new WechatPayDataWithBLOBsMo();

        // 更新微信支付订单数据
        // 成功
        paymentResponseDTO.setPayId(list.get(0).getId());
        if (PayReturnCodeEnum.SUCCESS.getCode().equals(response.getCode())) {
            if (WechatPayEnums.OrderTypeEnum.MERCHANT_PAY.getType().equals(request.getOrderType())) {
                // 商户转个人
                updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_SUCCESS.getStatus());
                updateWechatDataMo.setRemark(WechatPayConstants.SUCCESS);
                updateWechatDataMo.setPaymentNo(paymentResponseDTO.getPaymentNo());
            } else {
                // 个人转商户
                updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_AWAIT.getStatus());
            }

        } else if (PayReturnCodeEnum.THIRD_SYSTEM_ERROR.getCode().equals(response.getCode())) {
            // 第三方支付系统异常
            updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_SYSTEM_ERROR.getStatus());
            updateWechatDataMo.setMsg(response.getMsg());
            updateWechatDataMo.setRemark(WechatPayConstants.SYSTEMERROR);
        } else {
            // 失败
            updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_FAILED.getStatus());
            updateWechatDataMo.setMsg(response.getMsg());
            updateWechatDataMo.setRemark(WechatPayConstants.FAIL);
        }

        updateWechatDataMo.setResponseTime(new Date());
        updateWechatDataMo.setResponse(JSON.toJSONString(context.getResultMap()));
        int count = wechatPayDataMapper.updateByExampleSelective(updateWechatDataMo, updateWechatDataExampleMo);
        if (count < 1) {
            log.error("微信支付订单同步回调更新订单数据失败 ==> id:[{}],nonceStr:[{}]", list.get(0).getId(), paymentContext.getNonceStr());
        }
    }


    @Override
    public String getPayChannel() {
        return PayChannelEnum.WECHAT_PAY.getCode();
    }

    /**
     * 将对象装换为map
     *
     * @param bean
     * @return
     */
    private static <T> Map<String, String> beanToMap(T bean) {
        Map<String, String> map = new HashMap<>(8);
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                if (beanMap.get(key) != null) {
                    if (key.toString().equals("packageValue")) {
                        map.put("package", (String) beanMap.get(key));
                    } else {
                        map.put(key + "", (String) beanMap.get(key));
                    }
                }
            }
        }
        return map;
    }

    @Override
    public AbstractResponse completePayment(String result) throws Exception {
        try {
            log.info("微信支付异步回调completePayment请求参数:[{}]", result);
            this.initPayConfigMO();
            PaymentNotifyResponseDTO response = new PaymentNotifyResponseDTO();

            Map<String, String> resultMap = WechatPayUtil.xmlToMap(result);

            // 验证签名
            boolean flag = WechatPayUtil.isSignatureValid(resultMap, threadLocal.get().getPayKey());
            String nonceStr = resultMap.get(WechatPayConstants.NONCE_STR);
            response.setNumber(nonceStr);
            if (!flag) {
                log.error("微信支付异步回调签名失败,[{}]", JSON.toJSONString(result));
                return response;
            }

            log.info("微信支付异步回调签名成功!");

            // 返回code为失败
            if (WechatPayConstants.FAIL.equals(resultMap.get(WechatPayConstants.RETURN_CODE))) {
                log.error("微信支付异步回调 ==> return_code=FAIL");
                return response;
            }


            WechatPayDataExampleMo selectMo = new WechatPayDataExampleMo();
            selectMo.createCriteria().andNonceStrEqualTo(nonceStr);

            List<WechatPayDataMo> list = wechatPayDataMapper.selectByExample(selectMo);

            if (CollectionUtils.isEmpty(list)) {
                log.error("微信异步回调:获取支付订单数据异常! ==> nonceStr:[{}]", nonceStr);
                return response;
            }

            WechatPayDataMo wechatDataMo = list.get(0);

            // 订单状态是==>支付成功
            if (WechatPayEnums.PayStatusEnum.PAY_SUCCESS.getStatus().equals(wechatDataMo.getStatus())) {
                log.error("微信异步回调:支付订单数据状态为支付成功,无需处理! ==> id:[{}],nonceStr:[{}]",
                        wechatDataMo.getId(), nonceStr);
                response.setResult(WechatPayUtil.setXML(WechatPayConstants.SUCCESS, WechatPayConstants.OK));
                return response;
            }

            // 支付状态不是==>预订单初始状态/已同步回调,待支付
            if (!WechatPayEnums.PayStatusEnum.PAY_AWAIT.getStatus().equals(wechatDataMo.getStatus())) {
                log.error("微信异步回调:支付订单数据状态异常:不是预订单初始状态/已同步回调,待支付! ==> id:[{}],nonceStr:[{}]",
                        wechatDataMo.getId(), nonceStr);
                return response;
            }

            if (!wechatDataMo.getTotalFee().toString().equals(resultMap.get(WechatPayConstants.TOTAL_FEE))) {
                log.error("微信异步回调:回调金额total_fee和支付订单totalFee不一致! ==> id:[{}],nonceStr:[{}]",
                        wechatDataMo.getId(), nonceStr);
                return response;
            }


            // 异步回调成功,更新订单数据信息
            Boolean returnOrderCode = true;
            WechatPayDataWithBLOBsMo updateWechatDataMo = new WechatPayDataWithBLOBsMo();
            updateWechatDataMo.setCallbackTime(new Date());
            updateWechatDataMo.setCallback(JSON.toJSONString(resultMap));
            if (WechatPayConstants.SUCCESS.equals(resultMap.get(WechatPayConstants.RESULT_CODE))) {
                // 更新订单数据状态为支付成功
                updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_SUCCESS.getStatus());
            } else {
                // 更新订单数据状态为支付失败
                updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_FAILED.getStatus());
                returnOrderCode = false;
            }

            WechatPayDataExampleMo updateWechatDataExampleMo = new WechatPayDataExampleMo();
            updateWechatDataExampleMo.createCriteria().andIdEqualTo(list.get(0).getId())
                    .andStatusEqualTo(WechatPayEnums.PayStatusEnum.PAY_AWAIT.getStatus());

            int count = wechatPayDataMapper.updateByExampleSelective(updateWechatDataMo, updateWechatDataExampleMo);
            if (count < 1) {
                log.error("微信异步回调:支付订单更新订单数据失败! ==> id:[{}],nonceStr:[{}]", list.get(0).getId(), nonceStr);
                return response;
            }

            //TODO 需要回调订单服务
            try {
                DisbOrderPayDoneParamDTO orderStateMachineParamDTO = new DisbOrderPayDoneParamDTO();
                orderStateMachineParamDTO.setEvent(EventEnum.DISB_PAYDONE.getValue());
                orderStateMachineParamDTO.setData(PayDonePramDTO.builder().code(returnOrderCode)
                        .orderNo(wechatDataMo.getOrderNo())
                        .wechatDataId(wechatDataMo.getId().toString())
                        .kpayOrderNo(resultMap.get(WechatPayConstants.ATTACH)).build());
                String execute = orderFacade.execute(JSON.toJSONString(orderStateMachineParamDTO));
                log.info("微信支付异步回调成功,通知orderFacade.execute==> result:[{}]", JSON.toJSONString(execute));
            } catch (Exception e) {
                log.error("微信支付异步回调成功,通知订单服务异常:", e);
            }

            response.setResult(WechatPayUtil.setXML(WechatPayConstants.SUCCESS, WechatPayConstants.OK));
            return response;
        } finally {
            this.finallyProcess();
        }
    }

    @Override
    public Map<String, String> queryOrder(String orderNo) throws Exception {
        try {
            this.initPayConfigMO();
            WechatPaymentContext context = new WechatPaymentContext();
            context.setAppid(threadLocal.get().getAppId());
            context.setMchId(threadLocal.get().getMchId());
            context.setOutTradeNo(orderNo);
            context.setNonceStr(WechatPayUtil.generateNonceStr());
            SerializeConfig config = new SerializeConfig();
            config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
            String str = JSON.toJSONString(context, config);

            Map<String, String> paraMap = JSON.parseObject(str, HashMap.class);
            String xml = WechatPayUtil.generateSignedXml(paraMap, threadLocal.get().getPayKey());
            String result = HttpClientUtil.httpPost(tradeDynamicPropertyService.getWechatOrderQuery(), xml);
            return WechatPayUtil.xmlToMap(result);
        } finally {
            this.finallyProcess();
        }
    }

    @Override
    public void finallyProcess() {
        threadLocal.remove();
    }

    public static void main(String[] args) throws Exception {
        //序列化驼峰转下划线
        /*WechatPaymentContext context = new WechatPaymentContext();
        context.setSpbillCreateIp("127.0.0.1");
        context.setTradeType("type");
        context.setProductId("1");
        SerializeConfig config = new SerializeConfig();
        config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
        String s = JSON.toJSONString(context, config);
        System.out.println(s);*/

        String str = "<xml><appid><![CDATA[wx4f9521f88802fb91]]></appid>\\n<bank_type><![CDATA[CFT]]></bank_type>\\n<cash_fee><![CDATA[1]]></cash_fee>\\n<fee_type><![CDATA[CNY]]></fee_type>\\n<is_subscribe><![CDATA[Y]]></is_subscribe>\\n<mch_id><![CDATA[1295326001]]></mch_id>\\n<nonce_str><![CDATA[QiP9kRWGe5KipZS7mUeI4AkPS7BYhCeR]]></nonce_str>\\n<openid><![CDATA[oMQijvzhCa4RAPtIdE9jPTP8KO6w]]></openid>\\n<out_trade_no><![CDATA[41b2ce4a56c24888be55645f9fc503f2]]></out_trade_no>\\n<result_code><![CDATA[SUCCESS]]></result_code>\\n<return_code><![CDATA[SUCCESS]]></return_code>\\n<sign><![CDATA[1403AD406C49DC0565CF2561D12EA0CD]]></sign>\\n<time_end><![CDATA[20181222160654]]></time_end>\\n<total_fee>1</total_fee>\\n<trade_type><![CDATA[JSAPI]]></trade_type>\\n<transaction_id><![CDATA[4200000224201812220529619364]]></transaction_id>\\n</xml>";
        Map<String, String> stringStringMap = WechatPayUtil.xmlToMap(str);
        System.out.println(stringStringMap);

    }

}
